Texture2D txDiffuse : register(t0);
SamplerState samLinear : register(s0); 

cbuffer cbMain : register(b0)
{
	matrix g_mWorld;                            // World matrix
	matrix g_mView;                             // View matrix
	matrix g_mProjection;                       // Projection matrix
	matrix g_mViewProjection;                   // VP matrix
	matrix g_mWorldViewProjection;              // WVP matrix
	matrix g_mInvView;                          // Inverse of view matrix
	float4 g_vScreenResolution;                 // Screen resolution

	float4 g_vMeshColor;                        // Mesh color
	float4 g_vTessellationFactor;               // Edge, inside, minimum tessellation factor and 1/desired triangle size
	float4 g_vDetailTessellationHeightScale;    // Height scale for detail tessellation of grid surface
	float4 g_vGridSize;                         // Grid size

	float4 g_vDebugColorMultiply;               // Debug colors
	float4 g_vDebugColorAdd;                    // Debug colors

	float4 g_vFrustumPlaneEquation[4];          // View frustum plane equations
};

cbuffer cbMaterial : register(b1)
{
	float4 	 g_materialAmbientColor;          	// Material's ambient color
	float4 	 g_materialDiffuseColor;          	// Material's diffuse color
	float4 	 g_materialSpecularColor;         	// Material's specular color
	float4 	 g_fSpecularExponent;             	// Material's specular exponent

	float4 	 g_LightPosition;                 	// Light's position in world space
	float4 	 g_LightDiffuse;                  	// Light's diffuse color
	float4 	 g_LightAmbient;                  	// Light's ambient color

	float4 	 g_vEye;					    	// Camera's location
	float4 	 g_fBaseTextureRepeat;		    	// The tiling factor for base and normal map textures
	float4 	 g_fPOMHeightMapScale;		    	// Describes the useful range of values for the height field

	float4   g_fShadowSoftening;		    	// Blurring factor for the soft shadows computation

	int      g_nMinSamples;				    	// The minimum number of samples for sampling the height field profile
	int      g_nMaxSamples;				    	// The maximum number of samples for sampling the height field profile
};

//####################################################################################################################




/*cbuffer ConstantBuffer : register( b0 )
{
	matrix World;
	matrix View;
	matrix Projection;
	float4 vLightDir[2];
	float4 vLightColor[2];
	float4 vOutputColor;
}*/

struct Material 
{
	float Ka, Kd, Ks, A;
};
struct DirectionalLight
{
	float4 color;
	float3 dir;
};
//--------------------------------------------------------------------------------------
struct VS_INPUT
{
    float4 pos : POSITION;
	float3 norm : NORMAL;
	float2 tex : TEXCOORD0;
};
struct VS_OUTPUT_HS_INPUT
{
    float4 pos : SV_POSITION;
	float3 norm : NORMAL;
	float2 tex : TEXCOORD0;
};
struct GS_INPUT
{
	float4 pos : SV_POSITION;
	float3 norm : NORMAL;
	float2 tex : TEXCOORD0;
};


//#################################################
struct HS_CONSTANT_OUTPUT
{
	float edges[3]  : SV_TessFactor;
	float inside : SV_InsideTessFactor;
};
struct HS_OUTPUT_DS_INPUT
{
	float3 pos  : POSITION;
	float3 norm : NORMAL;
	float2 tex : TEXCOORD0;
};
struct DS_OUTPUT
{
	float4 pos  : SV_POSITION;
	float3 norm : NORMAL;
	float2 tex : TEXCOORD0;
	float4 color     : COLOR;
};

HS_CONSTANT_OUTPUT HSConstant(InputPatch<VS_OUTPUT_HS_INPUT, 3> ip, uint pid : SV_PrimitiveID)
{
	HS_CONSTANT_OUTPUT output;

	float edge = 6.0f;
	float inside = 6.0f;

	output.edges[0] = edge;
	output.edges[1] = edge;
	output.edges[2] = edge;

	output.inside = inside;

	return output;
}


[domain("tri")]
[partitioning("fractional_odd")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(3)]
[patchconstantfunc("HSConstant")]
HS_OUTPUT_DS_INPUT HS(InputPatch<VS_OUTPUT_HS_INPUT, 3> ip, uint cpid : SV_OutputControlPointID, uint pid : SV_PrimitiveID)
{
	HS_OUTPUT_DS_INPUT Output;
	Output.pos = ip[cpid].pos;
	Output.norm = ip[cpid].norm;
	Output.tex = ip[cpid].tex;

	return Output;
}

[domain("tri")]
DS_OUTPUT DS(HS_CONSTANT_OUTPUT input, float3 UV : SV_DomainLocation, const OutputPatch<HS_OUTPUT_DS_INPUT, 3> patch)
{
	DS_OUTPUT Output;

	float3 vWorldPos = UV.x * patch[0].pos +
		UV.y * patch[1].pos +
		UV.z * patch[2].pos;

	matrix xxx = mul(g_mWorld,mul(g_mView,g_mProjection));

	Output.pos = mul(float4(vWorldPos, 1.0f), g_mWorldViewProjection);
	//Output.pos = mul(Output.pos, g_mView);
	//Output.pos = mul(Output.pos, g_mWorldViewProjection);

	//Output.norm = input.norm;
	//Output.tex = input.tex;

	return Output;
}


//#################################################




float4 calcPhongLighting(Material M, float4 LColor, float3 N, float3 L, float3 V, float3 R, float4 ambientLight)
{
	float4 Ia = M.Ka * ambientLight;
		float4 Id = M.Kd * saturate(dot(N, L));
		float4 Is = M.Ks * pow(saturate(dot(V, R)), M.A);

		return Ia + (Id + Is)*LColor;
}

//--------------------------------------------------------------------------------------
// Vertex Shader
//--------------------------------------------------------------------------------------	
VS_OUTPUT_HS_INPUT VS(VS_INPUT input)
{
	VS_OUTPUT_HS_INPUT output = (VS_OUTPUT_HS_INPUT)0;


	output.pos = input.pos;
	//output.wp = mul(input.Pos, World);
    //output.Pos = mul( input.Pos, World );
    //output.Pos = mul( output.Pos, View );
    //output.Pos = mul( output.Pos, Projection );
    //output.Norm = mul( float4( input.Norm, 1 ), World ).xyz;
	//output.Pos.xyz *= txDiffuse.Sample(samLinear, input.Tex).x;
	
	//output.Tex = input.Tex;

	return output;
}


//--------------------------------------------------------------------------------------
// Pixel Shader
//--------------------------------------------------------------------------------------
/*float4 PS( PS_INPUT input) : SV_Target
{
    float4 finalColor = 0;
    //do NdotL lighting for 2 lights
    for(int i=0; i<2; i++){finalColor +=  saturate (dot( (float3)vLightDir[i],input.Norm) * vLightColor[i]) ;}
    finalColor.a = 1;
	return finalColor;
}*/
float4 PS_GLASS(DS_OUTPUT input) : SV_Target
{
	/*
	float4 finalColor = 0;

	float3 eye = float3(0.0f, 4.0f, -10.0f);
	float4 lightColor = vLightColor[1];
	float3 lightDir = (float3)vLightDir[1];
	float3 N = normalize(mul(input.Norm, (float3x3) World));
	float3 V = normalize(-eye);
	float3 R = reflect(lightDir, N);


	Material m;
	m.Ka = 0.5;
	m.Kd = 0.5;
	m.Ks = 0.8;
	m.A = 16;

	float4 l = calcPhongLighting(m, lightColor, N, lightDir, V, R, vOutputColor);

	finalColor = vOutputColor;
	finalColor += saturate(dot((float3)lightDir, input.Norm) * lightColor);

	finalColor.a = 1;
	

	return l * txDiffuse.Sample(samLinear, input.Tex);*/
	return float4(1.0, 0.0, 0.0, 1.0);
}

float4 PS(DS_OUTPUT input) : SV_Target
{
	
	/*float4 finalColor = 0;

	float3 eye = float3(0.0f, 4.0f, -10.0f);
	float4 lightColor = vLightColor[1];
	float3 lightDir = (float3)vLightDir[1];
	float3 N = normalize(mul(input.Norm, (float3x3) World));
	float3 V = normalize(-eye);
	float3 R = reflect(lightDir, N);


	Material m;
	m.Ka = 0.5;
	m.Kd = 0.5;
	m.Ks = 0.8;
	m.A = 16;

	float4 l = calcPhongLighting(m, lightColor, N, lightDir, V, R, vOutputColor);

	finalColor = vOutputColor;
	finalColor += saturate(dot((float3)lightDir, input.Norm) * lightColor);
	
	finalColor.a = 1;
	

	return l * txDiffuse.Sample(samLinear, input.Tex);*/

	return float4(1.0, 0.0, 0.0, 1.0);
}


[maxvertexcount(12)]
void GSMain(triangle GS_INPUT input[3], inout LineStream<GS_INPUT> outputStream)
{
	/*GS_INPUT output;

	for (int i = 0; i < 3; ++i)
	{
		outputStream.Append(input[i]);
	}
	outputStream.RestartStrip();*/
}


//--------------------------------------------------------------------------------------
// PSSolid - render a solid color
//--------------------------------------------------------------------------------------
float4 PSSolid(DS_OUTPUT input) : SV_Target
{
    return float4(1.0,0.0,0.0,1.0);
}
